package es.unex.meigas.gvsig.core;

import java.io.File;
import java.io.IOException;
import java.sql.Types;

import com.hardcode.gdbms.engine.data.DataSource;
import com.hardcode.gdbms.engine.data.driver.DriverException;
import com.hardcode.gdbms.engine.data.driver.FileDriver;
import com.iver.cit.gvsig.fmap.core.IFeature;
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
import com.iver.cit.gvsig.fmap.edition.DefaultRowEdited;
import com.iver.cit.gvsig.fmap.edition.EditableAdapter;
import com.iver.cit.gvsig.fmap.edition.IWriteable;
import com.iver.cit.gvsig.fmap.edition.IWriter;
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
import com.iver.cit.gvsig.project.ProjectFactory;
import com.iver.cit.gvsig.project.documents.table.ProjectTable;

import es.unex.meigas.dataObjects.AbstractTable;
import es.unex.meigas.dataObjects.IRecordsetIterator;

public class gvTable extends AbstractTable {

	private Object m_BaseDataObject;
	private String m_sName;
	private String m_sFilename;

	public String getName() {

		if (m_BaseDataObject instanceof ProjectTable){
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			return table.getName();
		}
		else{
			return m_sName;
		}

	}

	public void create(Object obj) {

		if (obj instanceof ProjectTable){
			m_BaseDataObject = obj;
		}

	}

	public void create(String sName, String sFilename, Class[] types, String[] sFields) {

		m_sFilename = sFilename;
		TableMemoryDriver table = new TableMemoryDriver(sFields, DataTools.getgvSIGTypes(types));
		m_sName = sName;
		m_BaseDataObject = table;

	}

	public void addRecord(Object[] record) {

		if (m_BaseDataObject instanceof TableMemoryDriver) {
			TableMemoryDriver table = (TableMemoryDriver) m_BaseDataObject;
			table.addRow(DataTools.getGVSIGValues(record));
		}

	}

	public IRecordsetIterator iterator() {

		return new gvRecordsetIterator(m_BaseDataObject);

	}

	public String getFieldName(int i) {

		if (m_BaseDataObject instanceof ProjectTable) {
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			try {
				return table.getModelo().getRecordset().getFieldName(i);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				return "";
			}
		}
		else{
			TableMemoryDriver table = (TableMemoryDriver) m_BaseDataObject;
			try {
				return table.getFieldName(i);
			} catch (DriverException e) {
				return "";
			}
		}

	}

	public Class getFieldType(int i) {

		if (m_BaseDataObject instanceof ProjectTable) {
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			try {
				int iType = table.getModelo().getRecordset().getFieldType(i);
				return DataTools.getTypeClass(iType);
			} catch (Exception e) {
				return String.class;
			}
		}
		else{
			TableMemoryDriver table = (TableMemoryDriver) m_BaseDataObject;
			int iType;
			try {
				iType = table.getFieldType(i);
				return DataTools.getTypeClass(iType);
			} catch (DriverException e) {
				return String.class;
			}
		}

	}

	public int getFieldCount() {

		if (m_BaseDataObject instanceof ProjectTable) {
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			try {
				return table.getModelo().getRecordset().getFieldCount();
			} catch (Exception e) {
				return 0;
			}
		}
		else{
			TableMemoryDriver table = (TableMemoryDriver) m_BaseDataObject;
			try {
				return table.getFieldCount();
			} catch (DriverException e) {
				return 0;
			}
		}

	}

	public long getRecordCount() {

		if (m_BaseDataObject instanceof ProjectTable) {
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			try {
				return table.getModelo().getRecordset().getRowCount();
			} catch (Exception e) {
				return 0;
			}
		}
		else{
			TableMemoryDriver table = (TableMemoryDriver) m_BaseDataObject;
			try {
				return table.getRowCount();
			} catch (DriverException e) {
				return 0;
			}
		}

	}

	public void postProcess() {

		SelectableDataSource source;
		ITableDefinition orgDef;
		FileDriver driver;
		File file;
		try {
			LayerFactory.getDataSourceFactory().addDataSource((TableMemoryDriver)m_BaseDataObject,
					m_sName);
			DataSource dataSource = LayerFactory.getDataSourceFactory().
			createRandomDataSource(m_sName);
			dataSource.start();
			SelectableDataSource sds = new SelectableDataSource(dataSource);
			EditableAdapter auxea = new EditableAdapter();
			auxea.setOriginalDataSource(sds);
			ProjectTable table = ProjectFactory.createTable(m_sName, auxea);
			file = new File(m_sFilename);
			driver = (FileDriver) LayerFactory.getDM().getDriver("gdbms dbf driver");
			source = table.getModelo().getRecordset();
			source.start();
			orgDef = table.getModelo().getTableDefinition();
		} catch (Exception e) {
			return;
		}

		try {
			if (!file.exists()){
				driver.createSource(file.getAbsolutePath(),new String[] {"0"},new int[] {Types.INTEGER} );
				file.createNewFile();
			}
			driver.open(file);
		} catch (IOException e) {
			return;
		}

		IWriter writer = ((IWriteable)driver).getWriter();
		try {
			writer.initialize(orgDef);
			writer.preProcess();
			SourceIterator sourceIter = new SourceIterator(source);
			IFeature feature;
			int i=0;
			while (sourceIter.hasNext()){
				 feature = sourceIter.nextFeature();

				 DefaultRowEdited edRow = new DefaultRowEdited(feature,
						 DefaultRowEdited.STATUS_ADDED, i);
				 writer.process(edRow);
				 i++;
			}
			writer.postProcess();
		} catch (Exception e) {
			return;
		}

		ProjectTable table = FileTools.openTable(m_sFilename, m_sName);
		create(table);

	}

	public void open() {

		if (m_BaseDataObject instanceof ProjectTable){
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			try {
				table.getModelo().getRecordset().start();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

	public void close() {

		if (m_BaseDataObject instanceof ProjectTable){
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			try {
				table.getModelo().getRecordset().stop();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

	public String getFilename() {

		return m_sFilename;

	}

	public void setName(String name) {

		if (m_BaseDataObject instanceof ProjectTable){
			ProjectTable table = (ProjectTable) m_BaseDataObject;
			table.setName(name);
		}
		else{
			m_sName = name;
		}

	}

	public Object getBaseDataObject() {

		return m_BaseDataObject;

	}


}
